#include "obj_fn.h"
#include "meta_obj.h"
#include "vm.h"
#include "class.h"

/**
 * @brief 创建upvalue对象
*/
ObjUpvalue* new_objUpvalue(VM *vm, Value *local_var_ptr)
{
    ObjUpvalue *obj_upvalue = ALLOCATE(vm, ObjUpvalue);
    init_objheader(vm, &obj_upvalue->obj_header, OT_UPVALUE, NULL);
    obj_upvalue->local_var_ptr = local_var_ptr;
    obj_upvalue->closed_upvalue = VT_TO_VALUE(VT_NULL);
    obj_upvalue->next = NULL;
    return obj_upvalue;
}

/**
 * @brief 以函数fn创建一个闭包
*/
ObjClosure* new_objClosure(VM *vm, ObjFn *obj_fn)
{
        ObjClosure *obj_closure = ALLOCATE_EXTRA(vm, ObjClosure, sizeof(ObjUpvalue *) * obj_fn->upvalue_num);

        init_objheader(vm, &obj_closure->obj_header, OT_CLOSURE, vm->fn_class);
        obj_closure->fn = obj_fn;

        // 清除upvalue 避免在填充upvalue数组之前处罚GC
        uint32_t idx = 0;
        while (idx < obj_fn->upvalue_num)
        {
            obj_closure->upvalues[idx] = NULL;
            idx ++;
        }
        return obj_closure;
}

/**
 * @brief 创建一个空函数
*/
ObjFn* new_objFn(VM *vm, ObjModule *obj_module, uint32_t max_stack_slot_used_num)
{
    ObjFn *obj_fn = ALLOCATE(vm, ObjFn);
    if (obj_fn == NULL)
    {
        MEM_ERROR("allocate ObjFn failed!");
    }
    init_objheader(vm, &obj_fn->obj_header, OT_FUNCTION, vm->fn_class);
    Byte_buffer_init(&obj_fn->instruct_stream);
    Value_buffer_init(&obj_fn->constants);
    obj_fn->module = obj_module;
    obj_fn->max_stack_slot_used_num = max_stack_slot_used_num;
    obj_fn->upvalue_num = obj_fn->arg_num = 0;
#ifdef DEBUG    
    obj_fn->debug = ALLOCATE(vm, FnDebug);
    obj_fn->debug->fn_name = NULL;
    Int_buffer_init(&obj_fn->debug->lineNo);
#endif
    return obj_fn;
}